package system.dao.page;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;

import system.util.DateTimeUtil;


/**
 * Created by IntelliJ IDEA.
 * User: joeytang
 * Date: 2009-2-27
 * Time: 13:54:27
 * 过滤接口
 */
public class HibernateFilter implements CriteriaCommand {
    List<Filter> filters = new ArrayList<Filter>();
    //过滤重复的别�?
    Set<String> aliases = new HashSet<String>();

    /**
     * 添加过滤条件
     * @param property
     * @param value
     */
    public void addFilter(String property, Object value) {
        filters.add(new Filter(property, value));
    }

    /**
     * 加载过滤条件
     * @param criteria
     * @return
     */
    public Criteria execute(Criteria criteria) {
        for (Filter filter : filters) {
            buildCriteria(criteria, filter.getProperty(), filter.getValue());
        }
        if(null != aliases && aliases.size() > 0){
        	for(String a:aliases){
        		criteria.createAlias(a, a);
        	}
        }
        return criteria;
    }

    public List<Filter> getFilters() {
        return filters;
    }

    /**
     * 判断执行条件
     * @param criteria
     * @param property
     * @param value
     */
    @SuppressWarnings("deprecation")
    private void buildCriteria(Criteria criteria, String property, Object value) {

        if(property.indexOf(".")!=-1){
        	aliases.add(property.substring(0,property.indexOf(".")));
//        	criteria.createAlias(property.substring(0,property.indexOf(".")),property.substring(0,property.indexOf(".")));
//            criteria.createCriteria(property.substring(0,property.indexOf(".")),property.substring(0,property.indexOf(".")));
        }
        if (null == value) {
            return;
        }
        if (value instanceof String) {
            criteria.add(Restrictions.like(property, "%" + value + "%"));
            return;
        }
        if (value instanceof Boolean) {
            criteria.add(Restrictions.eq(property, value));
            return;
        }
        if (value instanceof Integer) {
            criteria.add(Restrictions.eq(property, value));
            return;
        }
        if (value instanceof Short) {
            criteria.add(Restrictions.eq(property, value));
            return;
        }
        if (value instanceof Date) {
            Date s = (Date) value;
            Date _begin = DateTimeUtil.begin(s);
            Date _end = DateTimeUtil.end(s);
            criteria.add(Restrictions.between(property, _begin, _end));
            return;
        }
        if (value instanceof Date[]) {
            Date[] date = (Date[]) value;
            criteria.add(Restrictions.between(property, date[0], date[1]));
            return;
        }
        if (value instanceof NotQuery) {
            NotQuery v = (NotQuery) value;
            criteria.add(Restrictions.ne(property, v.getObject()));
            return;
        }

        if (value instanceof IsNotNull) {
            IsNotNull v = (IsNotNull) value;
            criteria.add(Restrictions.isNotNull(property));
            return;
        }

        if (value instanceof IsNull) {
            IsNull v = (IsNull) value;
            criteria.add(Restrictions.isNull(property));
            return;
        }

        if (value instanceof Integer[]) {
            Integer[] vaInteg = (Integer[]) value;
            criteria.add(Restrictions.in(property, vaInteg));
            return;
        }

        if (value instanceof Double[]) {
            Double[] vaInteg = (Double[]) value;
            criteria.add(Restrictions.between(property, vaInteg[0], vaInteg[1]));
            return;
        }

        if (value instanceof Collection) {
            List vaInteg = (List) value;
            criteria.add(Restrictions.in(property, vaInteg));
            return;
        }
        criteria.add(Restrictions.eq(property, value));
    }


    public static class Filter {
        private final String property;
        private final Object value;

        public Filter(String property, Object value) {
            this.property = property;
            this.value = value;
        }

        public String getProperty() {
            return property;
        }

        public Object getValue() {
            return value;
        }
    }
}
